package com.fms.job;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fms.constant.MessageConstant;
import com.fms.entity.Attendance;
import com.fms.entity.AttendanceTask;
import com.fms.entity.SysUser;
import com.fms.exception.ServiceException;
import com.fms.mapper.AttendanceMapper;
import com.fms.mapper.SysUserMapper;
import com.fms.service.AttendanceService;
import com.fms.service.AttendanceTaskService;
import com.fms.util.CastUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@PersistJobDataAfterExecution//数据持久化
@DisallowConcurrentExecution//不允许并发执行
@RequiredArgsConstructor
@Slf4j
public class InitAttendanceJob extends QuartzJobBean {
    private final SysUserMapper sysUserMapper;
    private final AttendanceService attendanceService;
    private final AttendanceMapper attendanceMapper;
    private final AttendanceTaskService attendanceTaskService;
    @Value("${frm.default.image-url:}")
    private String defaultImageUrl;
    @Override
    @Transactional
    protected void executeInternal(JobExecutionContext context)  {
        log.info("自动初始化考勤任务开始");
        //获取信息
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        List<Long> deptIds = CastUtils.castList(jobDataMap.get(MessageConstant.JOB_MAP_DEPT_IDS), Long.class);
        Long taskId = (Long)jobDataMap.get(MessageConstant.JOB_MAP_TASK_IDS);
        log.info("正在获取角色id：{}与任务id：{}",deptIds,taskId);
        //修改任务状态->2:已生效
        log.info("修改任务状态->2:正在运行");
        if(!attendanceTaskService.lambdaUpdate().set(AttendanceTask::getStatus,2)
                .eq(AttendanceTask::getId, taskId)
                .update()){
            log.info("修改任务状态失败");
            throw new ServiceException("更改任务状态失败,"+taskId+"的初始化考勤失败");
        }
        log.info("修改任务状态成功");
        //通过角色id获取用户ids以创建用户签到
        for (Long deptId : deptIds) {
            List<SysUser> sysUsers = sysUserMapper.selectList(
                    new LambdaQueryWrapper<SysUser>()
                            .select(SysUser::getUsername)
                            .eq(SysUser::getDeptId, deptId)
                            .eq(SysUser::getStatus, 1)
            );
            if(sysUsers.isEmpty()){
                log.info("{}下无用户需要分配",deptId);
                return;
            }
            List<Attendance> attendances = new ArrayList<>();
            log.info("获取将要分配人员集合：{}", sysUsers);
            sysUsers.forEach(sysUser -> {
                        String username = sysUser.getUsername();
                        log.info("正在为{}分配签到任务：{}", username, taskId);
                        if(!attendanceMapper.selectList(new LambdaQueryWrapper<Attendance>()
                                .eq(Attendance::getUsername, username)
                                .ne(Attendance::getStatus,5)).isEmpty()){
                            //停止用户上一次任务
                            if (!attendanceService
                                    .lambdaUpdate()
                                    .set(Attendance::getStatus, 5)
                                    .eq(Attendance::getUsername, username)
                                    .update()) {
                                throw new ServiceException(username + "上次任务未成功停止仍在进行,无法开启考勤任务");
                            }
                        }else{
                            log.info("{}无未结束的签到任务", username);
                        }
                        attendances.add(Attendance.builder()
                                .taskId(taskId)
                                .username(username)
                                .inImgUrl(defaultImageUrl)
                                .outImgUrl(defaultImageUrl)
                                .date(LocalDate.now())
                                .status(1)
                                .build());
                        log.info("为{}分配签到任务：{}，成功加入容器", username, taskId);
                    }
            );
            log.info("批量插入容器获取成功：{},即将进行批量插入", attendances);
            //批量插入数据库
            if (!attendances.isEmpty()) {
                if (!attendanceService.saveBatch(attendances)) {
                    log.info("批量插入容器获取失败：{},初始化完失败", attendances);
                    throw new ServiceException(taskId + "的初始化考勤失败");
                }
            }
            log.info("批量插入容器获取成功：{},初始化完成", attendances);
        }
    }
}
